﻿using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using DevExpress.Utils.MVVM.Services;
using DotNetExtensions.AspNet.DevExpress.MVVM.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Habi.Solver.ViewModels
{
    public abstract class DocumentViewModel<TModule>: ISupportLogicalLayout where TModule : Module
    {
        public List<TModule> Modules { get; set; }
        protected bool IsLoaded { get; private set; }
        public virtual TModule SelectedModule { get; set; }
        public virtual TModule ActiveModule { get; protected set; }

        public DocumentViewModel()
        {
            Modules = CreateModules();
        }
        public virtual TModule DefaultModule { get { return Modules.First(); } }
        protected IDocumentManagerService DocumentManagerService { get { return this.GetService<IDocumentManagerService>(); } }
        protected ILayoutSerializationService LayoutSerializationService { get { return this.GetService<ILayoutSerializationService>(); } }
        public abstract List<TModule> CreateModules();

        private bool documentChanging;

        private const string ViewLayoutName = "DocumentViewModel";

        public IList<IGrouping<string, TModule>> ModuleGroups
        {
            get { return Modules.GroupBy(m => m.Category).ToList(); }
        }

        public bool CanSerialize => true;

        IDocumentManagerService ISupportLogicalLayout.DocumentManagerService => DocumentManagerService;

        public IEnumerable<object> LookupViewModels => null;

        public void Show(TModule module)
        {
            IDocument document = ShowCore(module);
            documentChanging = true;
            ActiveModule = module;
            documentChanging = false;
            DocumentShown(module, document);
        }

        protected virtual void DocumentShown(TModule module, IDocument document)
        {

        }

        public IDocument ShowCore(TModule module)
        {
            if (module == null || DocumentManagerService == null)
                return null;
            IDocument document = DocumentManagerService.FindDocumentByIdOrCreate(module.Type, x => CreateDocument(module));
            document.Show();
            return document;
        }
        protected virtual void OnSelectedModuleChanged(TModule oldModule)
        {
            if (IsLoaded && !documentChanging)
                Show(SelectedModule);
        }

        protected virtual void OnActiveModuleChanged(TModule oldModule)
        {
            SelectedModule = ActiveModule;
        }

        IDocument CreateDocument(TModule module)
        {
            var document = DocumentManagerService.CreateDocument(module.Type, null, this);
            document.Title = GetModuleTitle(module);
            document.DestroyOnClose = false;
            return document;
        }

        protected virtual string GetModuleTitle(TModule module)
        {
            return module.Title;
        }

        public virtual void OnClosing(CancelEventArgs cancelEventArgs)
        {
            PersistentLayoutHelper.PersistentLogicalLayout = this.SerializeDocumentManagerService();
            if (LayoutSerializationService != null)
            {
                PersistentLayoutHelper.PersistentViewsLayout[ViewLayoutName] = LayoutSerializationService.Serialize();
            }
            Messenger.Default.Send(new CloseAllMessage(cancelEventArgs));
            PersistentLayoutHelper.SaveLayout();
        }

        public virtual void OnLoaded(TModule module)
        {
            IsLoaded = true; Show(module);
        }
    }
}
